<template>
  <a-spin :spinning="spinLoading">
    <div class="plan-schedul mt-10px">
      <div class="relative">
        <div class="flex flex-col">
          <div class="vehicle-information border-bottom pl-10px" >
            <div>式样</div>
            <div>车号</div>
            <div>车辆型号</div>
            <div>车辆代号</div>
            <div>VIN</div>
            <div>ENG</div>
            <!-- <div>轮胎规格</div> -->
          </div>
          <div>
            <div :class="dateHeight" >未排期项目</div>
            <div v-for="item in dateList" :key="item.date" :class="dateHeight" :style="{background:item.isWeek ? 'rgba(5, 5, 5, 0.03)' : 'white'}">{{item.day}}</div>
          </div>
        </div>
        <div class="flex absolute top-0 left-100px h-100%"  style="user-select: none;">
          <div class="container" :style="{width:`${containerWidth}px`}" v-for="(item, taskIndex) in list" :key="item.refId">
            <div class="vehicle-information text-center">
              <div>{{ item.carNumber  }}</div>
              <div>{{ item.vehicleAlias }}</div>
              <div>{{ item.model }}</div>
              <div>{{ item.managementNumber }}</div>
              <div>{{ item.vin }}</div>
              <div>{{ item.engine }}</div>
              <!-- <div>{{ item.gg }}</div> -->
            </div>
            <div class="relative">
              <Vue3DraggableResizable
                v-for="(el, projectIndex) in item.testItemList"
                :key="el.uuid"
                :initW="el.width"
                :initH="el.height"
                :minH="initHeight"
                v-model:x="el.left"
                v-model:y="el.top"
                v-model:w="el.width"
                v-model:h="el.height"
                v-model:active="el.active"
                :disabledX="true"
                :disabledW="false"
                :parent="false"
                :draggable="!disabledDraggable"
                :resizable="!disabledDraggable"
                :handles="['bm']"
                @activated="activatedHandle(taskIndex, projectIndex)"
                @drag-end="dragEndHandle"
                @resize-end="resizeEndHandle"
                :title="el.testName"
                class="draggable-div"
                :style="{cursor:!disabledDraggable ? 'move' : 'pointer', left:el.left + 'px'}"
              >
                <span>{{ el.testName }}</span>
                <EditFilled @click.stop="handleViewRemark(el)" class="absolute top-0 right--25px cursor-pointer" title="备注"/>
                <InfoCircleFilled class="absolute top-0 right-0 color-red "/>
              </Vue3DraggableResizable>
            </div>
          </div>
        </div>
      </div>
    </div>
  </a-spin>
</template>

<script setup lang="ts">
  import { ref, inject, computed, onMounted } from 'vue';
  import Vue3DraggableResizable from 'vue3-draggable-resizable';
  import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css';
  import { Modal } from 'ant-design-vue';
  import { EditFilled, InfoCircleFilled } from '@ant-design/icons-vue';
  import { buildUUID } from '/@/utils/uuid';


  interface TestItemList{
    testName:string,
    testStartDate:string,
    testEndDate: string,
    active: boolean,
    duration:number ,
    width: number,
    height: number,
    top: number,
    left:number,
    vin:string,
    uuid:string,
  }
  interface ListItem{
    refId:string,
    vin:string,
    model:string,
    carNumber:string,
    vehicleCode?:string,
    managementNumber:string,
    engine:string,
    vehicleAlias:string,
    testItemList:TestItemList[]
  }

  interface DateListItem {
    date:string,
    day:string,
    isWeek:boolean
  }


  const dayjs: any = inject('$dayjs');

  const list = ref<ListItem[]>([]);
  // 试验计划开始时间
  const planStartDate = ref<string>("2023-04-01");
  // 试验计划结束时间
  const planEndDate = ref<string>("2023-05-25");
  // 任务下标
  const taskIndex = ref(0);
  // 项目下标
  const projectIndex = ref(0);

 
  const containerWidth = ref(200);

  // 初始高度
  const initHeight = ref(40);

  // 计划开始日期和结束日期之间的所有日期
  const dateList = ref<DateListItem[]>([]);

  const spinLoading = ref(false);

  // 禁用拖动
  const disabledDraggable = computed(()=> {
    return false;
  });

  // 日期高度
  const dateHeight = computed(()=>{
    return `border-bottom pl-10px h-${initHeight.value}px line-height-${initHeight.value}px`;
  })

  
  function handleData() {
    const res = [
      {
        refId: 3,
        carNumber: '汽油国6M15B',
        vehicleAlias: 'TV7156NM',
        model: 'MZEA11L-GEFNZC',
        managementNumber: 'E301',
        vin: 'LFMAL1CC8K0000027',
        engine: '0000157',
        // gg: '195/65R15',
        testItemList: [
          {
            testStartDate: '2023-04-08',
            testEndDate: '2023-04-08',
            testName: 'MT试验ECU改写（FTRD）',
          },
          {
            testStartDate: '2023-04-11',
            testEndDate: '2023-04-12',
            testName: '排放初期确认@FTRD',
          },
          {
            testStartDate: '2023-04-11',
            testEndDate: '2023-04-12',
            testName: '排放初期确认@FTRD',
          },
          {
            testStartDate: '2023-04-11',
            testEndDate: '2023-04-12',
            testName: '排放初期确认@FTRD',
          },
          {
            testStartDate: '2023-04-13',
            testEndDate: '2023-04-13',
            testName: '天津运输',
          },
          {
            testStartDate: '2023-04-14',
            testEndDate: '2023-04-20',
            testName: '5000km磨合',
          },
          {
            testStartDate: '2023-04-24',
            testEndDate: '2023-04-28',
            testName: '油耗（NEDC）如果E302结果合格，试验取消',
          },
          {
            testStartDate: '2023-04-21',
            testEndDate: '2023-04-21',
            testName: 'MT试验ECU改写（CATARC）',
          },
          {
            testStartDate: '2023-04-31',
            testEndDate: '2023-05-04',
            testName: '26（卤素高1）、27（卤素高）、后视镜安装、除霜、除雾、刮水器、外廓尺寸、60、油箱安装、99',
          },
          {
            testStartDate: '2023-05-07',
            testEndDate: '2023-05-11',
            testName: 'EMC(GB 34660)、ABS EMC',
          },
          {
            testStartDate: '2023-05-12',
            testEndDate: '2023-05-13',
            testName: '盐城运输',
          },
          {
            testStartDate: '2023-05-14',
            testEndDate: '2023-05-18',
            testName: '制动、ABS、加速噪声、定置噪声',
          },
          {
            testStartDate: '2023-05-19',
            testEndDate: '2023-05-20',
            testName: '天津运输',
          },
        ],
      },
      {
        refId: 1,
        carNumber: '汽油国6M15B',
        vehicleAlias: 'TV7156NM',
        model: 'MZEA11L-GEFNZC',
        managementNumber: 'E302',
        vin: 'LFMAL1CC5K0000017',
        engine: '0000158',
        // gg: '195/65R15',
        testItemList: [
          {
            testStartDate: '2023-04-10',
            testEndDate: '2023-04-11',
            testName: '排放初期确认@FTRD',
          },
          {
            testStartDate: '2023-04-08',
            testEndDate: '2023-04-08',
            testName: 'MT试验ECU改写（FTRD）',
          },
          {
            testStartDate: '2023-04-13',
            testEndDate: '2023-04-13',
            testName: '天津运输',
          },
        ],
      },
      {
        refId: 2,
        carNumber: '汽油国6M15B',
        vehicleAlias: 'TV7156N',
        model: 'MZEA11L-GEXNBC',
        managementNumber: 'E303',
        vin: 'LFMAL1CC7K0000018',
        engine: '0000159',
        // gg: '205/55R16',
        testItemList: [
          {
            testStartDate: '2023-04-08',
            testEndDate: '2023-04-08',
            testName: 'MT试验ECU改写（FTRD）',
          },
          {
            testStartDate: '2023-04-09',
            testEndDate: '2023-04-10',
            testName: '排放初期确认@FTRD',
          },
          {
            testStartDate: '2023-04-11',
            testEndDate: '2023-04-11',
            testName: '天津运输',
          },
        ],
      },
      {
        refId: 3,
        carNumber: '汽油国6M15B',
        vehicleAlias: 'TV7156N',
        model: 'MZEA11L-GEXNBC',
        managementNumber: 'E303',
        vin: 'LFMAL1CC7K0000018',
        engine: '0000159',
        // gg: '205/55R16',
        testItemList: [
          {
            testStartDate: '2023-04-08',
            testEndDate: '2023-04-08',
            testName: 'MT试验ECU改写（FTRD）',
          },
          {
            testStartDate: '2023-04-09',
            testEndDate: '2023-04-10',
            testName: '排放初期确认@FTRD',
          },
          {
            testStartDate: '2023-04-11',
            testEndDate: '2023-04-11',
            testName: '天津运输',
          },
        ],
      },
    ];
    res.forEach((item) => {
      item.testItemList.forEach((childItem) => {
        let duration = 1, top = 0;
        if(childItem.testStartDate && childItem.testEndDate){
          const { testStartDate, testEndDate } = childItem;
          duration = diffDay(testStartDate, testEndDate);
          top = diffDay(planStartDate.value, testStartDate) * initHeight.value;
        }
        Object.assign(childItem, {
          uuid:buildUUID(),
          vin:item.vin,
          active: false,
          duration ,
          width:110,
          height: duration * initHeight.value,
          left:50,
          top,
        });
      });
    });
    list.value = res;
    findOverlappingTests();
    console.log(list.value)
  }

  // 获取两个日期之间的所有日期，包括起始和结束日期
  function handleMonthlyDates() {
    dateList.value = [];
    let planSd = dayjs(planStartDate.value);
    const planEd = dayjs(planEndDate.value);
    while (planSd.isBefore(planEd) || planSd.isSame(planEd, 'day')) {
      const isWeek = planSd.day() === 0 || planSd.day() === 6;
      dateList.value.push({
        date:planSd.format('YYYY-MM-DD'),
        day:planSd.format('MM-DD'),
        isWeek
      });
      planSd = planSd.add(1, 'day');
    }
  }

  // 计算两个日期之间的天数差
  const diffDay = (start: string, end: string) => {
    const startDate = dayjs(start);
    const endDate = dayjs(end);
    const daysDifference = endDate.diff(startDate, 'day') + 1;
    return daysDifference;
  };

  // 根据天数获取某个日期后几天的日期
  const getDateByAddDuration = (date, duration) =>{
    return dayjs(date).add(duration, 'day').format('YYYY-MM-DD');
  }

  // 查看备注信息
  function handleViewRemark (data) {
    console.log(data);
      Modal.info({
      title:  "备注信息",
      content:data.title,
      onOk() {
        console.log('ok');
      },
    });
    
  }

  // 点击任务
  function activatedHandle(taskI, projectI) {
    taskIndex.value = taskI;
    projectIndex.value = projectI;
  }

  // 改变任务高度结束后
  function resizeEndHandle({ x, y, w, h }) {
    let testEndDate;
    // 拖动后的高度除初始高度，获得天数
    let duration = Math.round(h / initHeight.value);
    if (duration <= 0) duration = 1;
    const { testStartDate } = list.value[taskIndex.value].testItemList[projectIndex.value];
    testEndDate = getDateByAddDuration(testStartDate, duration - 1);

    // 更新数据
    const updateDataObj = {
      height:duration * initHeight.value,
      duration,
      testEndDate,
    }
    handleChangeData(updateDataObj);
  }

  // 拖动任务结束后
  async function dragEndHandle({ x, y }) {
    
    let top = 0, testStartDate, testEndDate;

    const heightDiff = (y - initHeight.value) % initHeight.value;

    // if (heightDiff == 0) return;

    // 距离顶部高度
    const distanceTopHeight = Math.round((y - initHeight.value) / initHeight.value) * initHeight.value + initHeight.value;
    if(heightDiff == 0){
      top = y;
    }else{
      top = heightDiff > 0 ? distanceTopHeight :initHeight.value;
    }
    // 计算距离计划开始日期天数
    let distancePlanStartDate = (distanceTopHeight - initHeight.value) / initHeight.value;
    distancePlanStartDate = distancePlanStartDate > 0 ? distancePlanStartDate : 0;
    if (distancePlanStartDate >= 0 ) {
      testStartDate = getDateByAddDuration(planStartDate.value, distancePlanStartDate);
      const duration = list.value[taskIndex.value].testItemList[projectIndex.value].duration;
      testEndDate = getDateByAddDuration(testStartDate, duration - 1);
    }
    // 更新数据
    const updateDataObj = {
      top,
      testStartDate,
      testEndDate,
    }
    handleChangeData(updateDataObj);
    
  }


  // 修改数据
  function handleChangeData(data, index = projectIndex.value) {
    Object.assign(list.value[taskIndex.value].testItemList[index], data);
    console.log(data)
  }


  // 找出与给定日期范围重叠的所有测试项及其下标  
  function findOverlappingTests() {  
    const { testStartDate: startDate, testEndDate: endDate, uuid } =  list.value[taskIndex.value].testItemList[projectIndex.value];
    const testItemList = list.value[taskIndex.value].testItemList;
    handleOverlappingTests(testItemList, startDate, endDate, containerWidth.value);
  } 
  // 封装处理重叠测试的逻辑
  function handleOverlappingTests(testItemList, startDate, endDate, containerWidth) {
    if (!testItemList || testItemList.length === 0) return;

    const overlappingTests = testItemList.reduce((acc, testItem, index) => {
      // 判断两个日期范围是否重叠
      const isOverlappingFlag = isOverlapping(startDate, endDate, testItem.testStartDate, testItem.testEndDate);
      if (isOverlappingFlag) {
        const left = index === 0 ? testItem.left : testItem.left + 55; 
        acc.push({ index, testItem, left });
      }
      return acc;
    }, []);

    // 根据重叠测试的数量调整宽度和左边距
    const widthPerItem = overlappingTests.length >= 3 ? containerWidth / overlappingTests.length : 50;
    overlappingTests.forEach((item, i) => {
      let left = item.left;
      if(overlappingTests.length >=3) {
        left = i == 0 ? 0 : i * widthPerItem;
      }else{
        left = i == 0 ? 50 : widthPerItem + 55;
      }
      handleChangeData({ width: widthPerItem, left }, item.index);
    });

    // 如果只有一个重叠的测试项目，单独处理
    if (overlappingTests.length === 1) {
      handleChangeData({ width: 110, left: 50, index: overlappingTests[0].index });
    }
  }

  // 检查两个日期范围是否重叠  
  function isOverlapping(startDate1: string, endDate1: string, startDate2: string, endDate2: string): boolean {  
    return !(  
      dayjs(endDate1).isBefore(dayjs(startDate2)) ||  
      dayjs(startDate1).isAfter(dayjs(endDate2))  
    );  
  }  



  onMounted(()=>{
    handleMonthlyDates()
    handleData();
  })
</script>
<style scoped lang="less">
.border-bottom{
  border-bottom:1px solid #ccc;
}
.no-data-icon{
  max-width: 400px;
  height: 300px;
  margin-right: 70px;
}
.plan-schedul{
  border: 1px solid #ccc;
  border-bottom: none;
  .vehicle-information{
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    & > div{
      height:25px;
      line-height:25px;
    }
  }
  .container {
    &:first-child{
      border-left: 1px solid #ccc;
    }
    height: 100%;
    border-right: 1px solid #ccc;
    .draggable-div {
      background-color: lightblue;
    }
  }
}
</style>
